package eggfly.speedtest;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Random;

/**
 * An example full-screen activity that shows and hides the system UI (i.e. status bar and navigation/system bar) with
 * user interaction.
 */
public class FullscreenActivity extends AppCompatActivity {

    private static final String TAG = "FullscreenActivity";

    private static final String[] LINKS = new String[]{
            "http://mirror.bit.edu.cn/apache/zookeeper/current/zookeeper-3.4.9.tar.gz", // 22M
            "http://mirror.bit.edu.cn/ubuntu-releases/16.10/ubuntu-16.10-desktop-amd64.iso", // 1.5G
            "http://releases.ubuntu.com/16.04/ubuntu-16.04.1-server-amd64.iso", // 667M
            "http://mirror.bit.edu.cn/ubuntu-releases/trusty/ubuntu-14.04.5-desktop-i386.iso.zsync", // 2.1M
    };

    private TextView mContentView;

    private Button mButton;

    private Random mRandom = new Random();

    private class DownloadTask extends AsyncTask<Void, String, Boolean> {

        private static final int BLOCK_SIZE = 16 * 1024;

        private static final long TEST_TIME_UNIT = 100;

        @Override
        protected void onProgressUpdate(String... values) {
            if (values != null && values.length > 0) {
                final String text = values[0];
                mContentView.setText(text);
            }
        }

        private final static int TIMEOUT = 20 * 1000;

        private final static long SLEEP_TIME = 10 * 1000;

        public String getContentLength(URLConnection conn) {
            // retrieve file size from Content-Length header field
            final String contentLength = conn.getHeaderField("Content-Length");
            return contentLength;
        }

        @Override
        protected Boolean doInBackground(Void... voids) {
            mTaskTimes++;
            try {
                final long pingStartTime = System.currentTimeMillis();
                final URL url = new URL(LINKS[mRandom.nextInt(LINKS.length)]);
                URLConnection conn = url.openConnection();
                conn.setConnectTimeout(TIMEOUT);
                conn.setReadTimeout(TIMEOUT);
                final String contentLength = getContentLength(conn);
                final long fileSize = Long.parseLong(contentLength);
                final InputStream is = conn.getInputStream();
                final long pingElapsedTime = System.currentTimeMillis() - pingStartTime;
                Log.d(TAG, "pingElapsedTime: " + pingElapsedTime + "ms");
                final byte[] buffer = new byte[BLOCK_SIZE];
                long totalDownloaded = 0;
                final long outerStartTime = System.currentTimeMillis();
                boolean finished = false;
                while (!isCancelled() && !finished) {
                    long totalBytes = 0;
                    final long startTime = System.currentTimeMillis();
                    long elapsedTime = 0;
                    while (elapsedTime <= TEST_TIME_UNIT) {
                        final int bytesRead = is.read(buffer);
                        if (bytesRead < 0) {
                            finished = true;
                            break;
                        }
                        elapsedTime = System.currentTimeMillis() - startTime;
                        totalBytes += bytesRead;
                        totalDownloaded += bytesRead;
                    }
                    final long totalElapsedTime = System.currentTimeMillis() - outerStartTime;
                    final String text = "URL: " + url + "\n"
                            + "Content length: " + contentLength + "\n"
                            + "Task times: " + mTaskTimes + "\n"
                            + "Speed: " + (int) ((totalBytes / 1024.0) / (elapsedTime / 1000.0)) + "kB/s\n"
                            + "Total elapsed time: " + (totalElapsedTime / 1000) + "s\n"
                            + "Total downloaded: " + (totalDownloaded / 1024) + "kB\n"
                            + "Average speed: " + (int) (totalDownloaded / 1024.0 / totalElapsedTime * 1000) + "kB/s\n"
                            + "Percent: " + (totalDownloaded * 1000 / fileSize) / 10.0 + "%\n";
                    publishProgress(text);
                }
                final String reason;
                if (isCancelled()) {
                    reason = "cancelled";
                } else if (finished) {
                    reason = "finished";
                } else {
                    reason = "unknown reason";
                }
                Log.d(TAG, reason);
                publishProgress(reason);
                delaySome();
                return true;
            } catch (IOException e) {
                e.printStackTrace();
                final String exception = e.toString();
                publishProgress(exception);
                delaySome();
                // error occurred
                return false;
            }
        }

        private void delaySome() {
            try {
                Thread.sleep(SLEEP_TIME);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        }

        @Override
        protected void onPostExecute(Boolean result) {
            Log.d(TAG, "onPostExecute: restart task");
            mTask = new DownloadTask();
            mTask.execute();
        }
    }

    private DownloadTask mTask;

    private int mTaskTimes = 0;

    private View.OnClickListener mOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (mTask == null || mTask.getStatus() != AsyncTask.Status.RUNNING) {
                mTask = new DownloadTask();
                mTask.execute();
                mButton.setText(R.string.interrupt);
            } else {
                mTask.cancel(true);
                mTask = null;
                mButton.setText(R.string.run);
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fullscreen);
        mContentView = (TextView) findViewById(R.id.fullscreen_content);
        mButton = (Button) findViewById(R.id.dummy_button);
        mButton.setOnClickListener(mOnClickListener);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
    }
}
